/****************************************************************************
 *  _____       ______  _____
 * |_   _|     |  ____|/ ____|
 *   | |  _ __ | |__  | (___    Institute of Embedded Systems
 *   | | | '_ \|  __|  \___ \   Zürcher Hochschule für Angewandte
 *  _| |_| | | | |____ ____) |  Wissenschaften
 * |_____|_| |_|______|_____/   8401 Winterthur, Switzerland
 *
 ****************************************************************************
 *
 * @version $Rev: 209 $
 * @author  $Author: bacr $
 * @date    $Date: 2014-01-09 10:44:54 +0100 (jeu., 09 janv. 2014) $
 *
 ***************************************************************************/

#ifndef __PTP2_DATASETS_H__
#define __PTP2_DATASETS_H__

#include "ptp2_types.h"

/* all dataset are host byte-order */
typedef struct ptp2_default_ds_t            ptp2_default_ds_t;
typedef struct ptp2_current_ds_t            ptp2_current_ds_t;
typedef struct ptp2_parent_ds_t             ptp2_parent_ds_t;
typedef struct ptp2_time_properties_ds_t    ptp2_time_properties_ds_t;
typedef struct ptp2_port_ds_t               ptp2_port_ds_t;
typedef struct ptp2_foreign_master_ds_t     ptp2_foreign_master_ds_t;

/** 8.2.1 defaultDS data set member specification: ordinary clock attributes */
struct ptp2_default_ds_t {
    /* static */
    bool                    two_step_clock;                     /**< 8.2.1.2.1 defaultDS.twoStepFlag: one- or two-step clock? */
    ptp2_clock_identity_t   clock_identity;                     /**< 8.2.1.2.2 defaultDS.clockIdentity: identity of local clock */
    uint8_t                 port_count;                         /**< 8.2.1.2.3 defaultDS.numberPorts: how many ports does the local clock have? */

    /* dynamic */
    ptp2_clock_quality_t    clock_quality;                      /**< 8.2.1.3.1 defaultDS.clockQuality */

    /* configurable */
    uint8_t                 priority1;                          /**< 8.2.1.4.1 defaultDS.priority1 */
    uint8_t                 priority2;                          /**< 8.2.1.4.2 defaultDS.priority2 */
    uint8_t                 domain_number;                      /**< 8.2.1.4.3 defaultDS.domainNumber */
    bool                    slave_only;                         /**< 8.2.1.4.4 defaultDS.slaveOnly: local clock is slave-only? */
    bool                        unicast_mode;                       /**< User defined: master is in unicast- (= true) or multicast-mode (= false) */
};

/** 8.2.2 currentDS data set member specification: synchronization attributes */
struct ptp2_current_ds_t {
    /* dynamic */
    uint16_t                steps_removed;                      /**< 8.2.2.2 currentDS.stepsRemoved: number of paths (intermediate devices) between local clock and grandmaster clock */
    ptp2_time_interval      offset_from_master;                 /**< 8.2.2.3 currentDS.offsetFromMaster: time difference between a master and a slave, computed by the slave */
    ptp2_time_interval      mean_path_delay;                    /**< 8.2.2.4 currentDS.meanPathDelay: mean propagation time (path delay) between a master and a slave, computed by the slave */
};

/** 8.2.3 parentDS data set member specification: parent and grandmaster attributes */
struct ptp2_parent_ds_t {
    /* dynamic */
    ptp2_port_identity_t    parent_port_identity;               /**< 8.2.3.2 parentDS.parentPortIdentity: port identity of the master port that issues sync messages to synchronize this clock */
    bool                    parent_stats;                       /**< 8.2.3.3 parentDS.parentStats: the parent has a port in slave-state and the parent clock has computed parent_offset_scaled_log_variance and parent_clock_phase_change_rate */
    uint16_t                parent_offset_scaled_log_variance;  /**< 8.2.3.4 parentDS.observedParentOffsetScaledLogVariance */
    int32_t                 parent_clock_phase_change_rate;     /**< 8.2.3.5 parentDS.observedParentClockPhaseChangeRate */
    ptp2_clock_identity_t   gm_identity;                        /**< 8.2.3.6 parentDS.grandmasterIdentity: clock identity of the grandmaster clock */
    ptp2_clock_quality_t    gm_clock_quality;                   /**< 8.2.3.7 parentDS.grandmasterClockQuality */
    uint8_t                 gm_priority1;                       /**< 8.2.3.8 parentDS.grandmasterPriority1 */
    uint8_t                 gm_priority2;                       /**< 8.2.3.9 parentDS.grandmasterPriority2 */
};

/** 8.2.4 timePropertiesDS data set member specification: timescale attributes */
struct ptp2_time_properties_ds_t {
    /* dynamic */
    int16_t                 current_utc_offset;                 /**< 8.2.4.2 timePropertiesDS.currentUtcOffset: offset between TAI and UTC, in seconds */
    bool                    current_utc_offset_valid;           /**< 8.2.4.3 timePropertiesDS.currentUtcOffsetValid: offset is known to be correct? */
    bool                    leap59;                             /**< 8.2.4.4 timePropertiesDS.leap59: adjust UTC time by indicating that the last minute of the current day contains 59 seconds */
    bool                    leap61;                             /**< 8.2.4.5 timePropertiesDS.leap61: adjust UTC time by indicating that the last minute of the current day contains 61 seconds */
    bool                    time_traceable;                     /**< 8.2.4.6 timePropertiesDS.timeTraceable: is the timescale and the offset traceable? */
    bool                    frequency_traceable;                /**< 8.2.4.7 timePropertiesDS.frequencyTraceable: is the frequency determining the timescale traceable? */
    bool                    ptp_timescale;                      /**< 8.2.4.8 timePropertiesDS.ptpTimescale: clock timescale is PTP (not ARB) */
    ptp2_time_source_t      time_source;                        /**< 8.2.4.9 timePropertiesDS.timeSource: source of time (information-only attribute) */
};

/** 8.2.5.4.4 portDS.delayMechanism */
typedef enum {
    PTP2_DELAY_MECHANISM_E2E = 0x01,
    PTP2_DELAY_MECHANISM_P2P = 0x02,
    PTP2_DELAY_MECHANISM_DISABLED = 0xFE
} ptp2_delay_mechanism_t;

/** 8.2.5 portDS data set member specification: port attributes */
struct ptp2_port_ds_t {
    /* static */
    ptp2_port_identity_t    port_identity;                      /**< 8.2.5.2.1 portDS.portIdentity -> ref 5.3.5: port identity of the local port */

    /* dynamic */
    ptp2_port_state_t       port_state;                         /**< 8.2.5.3.1 portDS.portState: current state of the protocol engine associated with this port */
    int8_t                  log_min_delay_req_interval;         /**< 8.2.5.3.2 portDS.logMinDelayReqInterval -> ref 7.7.2.4: minimum permitted mean time interval (min: as sync interval, max: 1/32 sync interval) */
    ptp2_time_interval      peer_mean_path_delay;               /**< 8.2.5.3.3 portDS.peerMeanPathDelay -> ref portDS.delayMechanism: P2P: current one-way propagation delay, E2E: not used (zero) */

    /* configurable */
    int8_t                      log_announce_interval;              /**< 8.2.5.4.1 portDS.logAnnounceInterval -> ref 7.7.2.2: mean interval between checking announce messages. the protocol engine checks each interval  (only in multicast mode) */
    uint8_t                 announce_receipt_timeout;           /**< 8.2.5.4.2 portDS.announceReceiptTimeout -> ref 7.7.3.1: timeout expires when receipt of an announce message before  */

    uint8_t                 foreign_master_threshold;           /**< 9.3.2.4.4 FOREIGN_MASTER_THRESHOLD: number of announce messages must be received to be qualified in STATE_DECISION_EVENT */
    uint8_t                 foreign_master_time_window;         /**< 9.3.2.4.4 FOREIGN_MASTER_TIME_WINDOW: number of retries to receive announce messages before counter gets reset (time window * 2^log_announce_interval in seconds) */

    int8_t                      log_sync_interval;                  /**< 8.2.5.4.3 portDS.logSyncInterval -> ref 7.7.2.3: mean interval between sync messages (only in multicast mode) */

    ptp2_delay_mechanism_t  delay_mechanism;                    /**< 8.2.5.4.4 portDS.delayMechanism */
    int8_t                  log_min_pdelay_req_interval;        /**< 8.2.5.4.5 portDS.logMinPdelayReqInterval */
    uint8_t                 version_number;                     /**< 8.2.5.4.6 portDS.versionNumber */

    bool                        not_slave;                          /**< ITU-T G.8275.1 6.6.1 a) never placed in SLAVE state, inverse of 8.2.1.4.4 defaultDS.slaveOnly */
    uint8_t                     local_priority;                     /**< ITU-T G.8275.1 6.6.1 c) tie-breaker in the dataset comparison algorithm, when all other attributes are equal */

    bool                        alternate_master;                   /**< User defined: alternate master flag (ref 17.4) per port, used by announce messages (ref 13.3.2.6: flagField) */
    bool                        profile_specific1;                  /**< User defined: PTP profile specific 1 (ref 17.4) per port, used by announce messages (ref 13.3.2.6: flagField) */
    bool                        profile_specific2;                  /**< User defined: PTP profile specific 2 (ref 17.4) per port, used by announce messages (ref 13.3.2.6: flagField) */
};

/** 9.3.2.4 foreignMasterDS data set member specification: implementation-specific data set */
struct ptp2_foreign_master_ds_t {
    ptp2_port_identity_t        port_identity;                  /**< 9.3.2.4.2 foreignMasterDS.foreignMasterPortIdentity: sourcePortIdentity field of an Announce message */
    uint8_t                     announce_msg_count;             /**< 9.3.2.4.3 foreignMasterDS.foreignMasterAnnounceMessages: the number of qualified Announce messages */

    /* last announce message fields */
    ptp2_port_identity_t        sender_identity;                    /**< User defined: foreign master port identity (= sourcePortIdentity) */
    ptp2_port_identity_t        receiver_identity;                  /**< User defined: local port identity */

    uint16_t                    steps_removed;                      /**< User defined: */

    uint8_t                     gm_priority1;                       /**< User defined: */
    ptp2_clock_quality_t        gm_clock_quality;                   /**< User defined: */
    uint8_t                     gm_priority2;                       /**< User defined: */
    ptp2_clock_identity_t       gm_identity;                        /**< User defined: */

    ptp2_time_properties_ds_t   time_properties_ds;                 /**< User defined: */
};

void ptp2_default_ds_init                                   (ptp2_default_ds_t *this);
void ptp2_default_ds_set_two_step_clock                     (ptp2_default_ds_t *this, bool two_step_clock);
void ptp2_default_ds_set_clock_identity                     (ptp2_default_ds_t *this, ptp2_clock_identity_t clock_identity);
void ptp2_default_ds_set_port_count                         (ptp2_default_ds_t *this, uint8_t port_count);
void ptp2_default_ds_set_clock_quality                      (ptp2_default_ds_t *this, uint8_t class, uint8_t accuracy);
void ptp2_default_ds_set_priority12                         (ptp2_default_ds_t *this, uint8_t priority, uint8_t priority2);
void ptp2_default_ds_set_priority1                          (ptp2_default_ds_t *this, uint8_t priority1);
void ptp2_default_ds_set_priority2                          (ptp2_default_ds_t *this, uint8_t priority2);
void ptp2_default_ds_set_domain_number                      (ptp2_default_ds_t *this, uint8_t domain_number);
void ptp2_default_ds_set_slave_only                         (ptp2_default_ds_t *this, bool slave_only);
void ptp2_default_ds_set_unicast_mode                       (ptp2_default_ds_t *this, bool unicast_mode);

void ptp2_current_ds_init                                   (ptp2_current_ds_t *this);
void ptp2_parent_ds_init                                    (ptp2_parent_ds_t *this);

void ptp2_time_properties_ds_init                           (ptp2_time_properties_ds_t *this);
void ptp2_time_properties_ds_set_current_utc_offset         (ptp2_time_properties_ds_t *this, int16_t current_utc_offset);
void ptp2_time_properties_ds_set_current_utc_offset_valid   (ptp2_time_properties_ds_t *this, bool current_utc_offset_valid);
void ptp2_time_properties_ds_set_leap59                     (ptp2_time_properties_ds_t *this, bool leap59);
void ptp2_time_properties_ds_set_leap61                     (ptp2_time_properties_ds_t *this, bool leap61);
void ptp2_time_properties_ds_set_time_traceable             (ptp2_time_properties_ds_t *this, bool time_traceable);
void ptp2_time_properties_ds_set_frequency_traceable        (ptp2_time_properties_ds_t *this, bool frequency_traceable);
void ptp2_time_properties_ds_set_ptp_timescale              (ptp2_time_properties_ds_t *this, bool ptp_timescale);
void ptp2_time_properties_ds_set_time_source                (ptp2_time_properties_ds_t *this, ptp2_time_source_t time_source);

void ptp2_port_ds_init                                      (ptp2_port_ds_t *this);
void ptp2_port_ds_set_port_identity                         (ptp2_port_ds_t *this, ptp2_clock_identity_t clock_identity, uint16_t port_number);
void ptp2_port_ds_set_clock_identity                        (ptp2_port_ds_t *this, ptp2_clock_identity_t clock_identity);
void ptp2_port_ds_set_port_state                            (ptp2_port_ds_t *this, ptp2_port_state_t port_state);
void ptp2_port_ds_set_log_min_delay_req_interval            (ptp2_port_ds_t *this, int8_t log_min_delay_req_interval);
void ptp2_port_ds_set_peer_mean_path_delay                  (ptp2_port_ds_t *this, ptp2_time_interval peer_mean_path_delay);
void ptp2_port_ds_set_log_announce_interval                 (ptp2_port_ds_t *this, int8_t log_announce_interval);
void ptp2_port_ds_set_announce_receipt_timeout              (ptp2_port_ds_t *this, uint8_t announce_receipt_timeout);
void ptp2_port_ds_set_foreign_master_threshold              (ptp2_port_ds_t *this, uint8_t foreign_master_threshold);
void ptp2_port_ds_set_foreign_master_time_window            (ptp2_port_ds_t *this, uint8_t foreign_master_time_window);
void ptp2_port_ds_set_log_sync_interval                     (ptp2_port_ds_t *this, int8_t log_sync_interval);
void ptp2_port_ds_set_delay_mechanism                       (ptp2_port_ds_t *this, ptp2_delay_mechanism_t delay_mechanism);
void ptp2_port_ds_set_log_min_pdelay_req_interval           (ptp2_port_ds_t *this, int8_t log_min_pdelay_req_interval);
void ptp2_port_ds_set_version_number                        (ptp2_port_ds_t *this, uint8_t version_number);
void ptp2_port_ds_set_not_slave                             (ptp2_port_ds_t *this, bool not_slave);
void ptp2_port_ds_set_local_priority                        (ptp2_port_ds_t *this, uint8_t local_priority);
void ptp2_port_ds_set_alternate_master                      (ptp2_port_ds_t *this, bool alternate_master, bool profile_specific1, bool profile_specific2);

void ptp2_foreign_master_ds_init                            (ptp2_foreign_master_ds_t *this);


#endif

